#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "numericalintegrator.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>
#include <QChart>
#include <QChartView>
#include <QLineSeries>
#include <QValueAxis>
#include <QAreaSeries>

QT_USE_NAMESPACE

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 设置图表
    QChart *chart = new QChart();
    chart->setTitle("曲线积分面积计算");
    ui->chartView->setChart(chart);
    ui->chartView->setRenderHint(QPainter::Antialiasing);

    // 连接信号槽
    connect(ui->btnLoad, &QPushButton::clicked, this, &MainWindow::onLoadData);
    connect(ui->btnCalculate, &QPushButton::clicked, this, &MainWindow::onCalculateArea);
    connect(ui->btnGenerate, &QPushButton::clicked, this, &MainWindow::onGenerateTestData);
    connect(ui->comboMethod, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &MainWindow::onMethodChanged);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onLoadData()
{
    QString fileName = QFileDialog::getOpenFileName(this, "打开数据文件", "",
                                                    "文本文件 (*.txt);;CSV文件 (*.csv);;所有文件 (*)");
    if (fileName.isEmpty()) return;

    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        showError("无法打开文件: " + fileName);
        return;
    }

    dataPoints.clear();
    QTextStream in(&file);
    int lineNumber = 0;

    while (!in.atEnd()) {
        QString line = in.readLine().trimmed();
        if (line.isEmpty() || line.startsWith("#")) continue;

        QStringList parts = line.split(" ", Qt::SkipEmptyParts);
        if (parts.size() < 2) {
            showError(QString("第 %1 行数据格式错误").arg(lineNumber + 1));
            return;
        }

        bool ok1, ok2;
        double x = parts[0].toDouble(&ok1);
        double y = parts[1].toDouble(&ok2);

        if (!ok1 || !ok2) {
            showError(QString("第 %1 行包含无效数字").arg(lineNumber + 1));
            return;
        }

        dataPoints.append(QPointF(x, y));
        lineNumber++;
    }

    file.close();

    if (dataPoints.size() < 2) {
        showError("数据点不足，至少需要2个点");
        return;
    }

    updatePlot();
    ui->statusbar->showMessage(QString("成功加载 %1 个数据点").arg(dataPoints.size()));
}

void MainWindow::onCalculateArea()
{
    if (dataPoints.size() < 2) {
        showError("请先加载数据或生成测试数据");
        return;
    }

    try {
        // 转换数据格式
        std::vector<double> x, y;
        for (const auto& point : dataPoints) {
            x.push_back(point.x());
            y.push_back(point.y());
        }

        // 获取选择的积分方法
        NumericalIntegrator::IntegrationMethod method;
        switch (ui->comboMethod->currentIndex()) {
            case 0: method = NumericalIntegrator::TrapezoidalRule; break;
            case 1: method = NumericalIntegrator::SimpsonsRule; break;
            case 2: method = NumericalIntegrator::BoolesRule; break;
            default: method = NumericalIntegrator::TrapezoidalRule;
        }

        // 计算面积
        double area = NumericalIntegrator::calculateArea(x, y, method);

        // 显示结果
        ui->labelResult->setText(QString("积分面积: %1").arg(area, 0, 'f', 6));
        ui->statusbar->showMessage(QString("计算完成 - 方法: %1").arg(ui->comboMethod->currentText()));

    } catch (const std::exception& e) {
        showError(QString("计算错误: %1").arg(e.what()));
    }
}

void MainWindow::onGenerateTestData()
{
    dataPoints.clear();

    // 生成测试数据：正弦曲线
    const int points = 100;
    const double xMin = 0.0;
    const double xMax = 2 * M_PI;

    for (int i = 0; i < points; ++i) {
        double x = xMin + (xMax - xMin) * i / (points - 1);
        double y = sin(x);
        dataPoints.append(QPointF(x, y));
    }

    updatePlot();
    ui->statusbar->showMessage(QString("生成 %1 个测试数据点").arg(points));
}

void MainWindow::onMethodChanged()
{
    // 根据选择的方法更新界面提示
    int index = ui->comboMethod->currentIndex();
    QString tip;

    switch (index) {
    case 0: // 梯形法则
        tip = "适用于任意间距的数据点";
        break;
    case 1: // 辛普森法则
        tip = "需要等间距且奇数个数据点";
        break;
    case 2: // 布尔法则
        tip = "需要等间距且4n+1个数据点";
        break;
    }

    // ui->labelMethodTip->setText(tip);
}

void MainWindow::updatePlot()
{
    QChart *chart = ui->chartView->chart();
    chart->removeAllSeries();

    // 创建曲线系列
    QLineSeries *series = new QLineSeries();
    series->setName("数据曲线");

    for (const auto& point : dataPoints) {
        series->append(point);
    }

    chart->addSeries(series);
    chart->createDefaultAxes();
    chart->axes(Qt::Horizontal).first()->setTitleText("X");
    chart->axes(Qt::Vertical).first()->setTitleText("Y");

    // 添加面积系列（可视化积分区域）
    QLineSeries *lowerSeries = new QLineSeries();
    for (const auto& point : dataPoints) {
        lowerSeries->append(point.x(), 0);
    }

    QAreaSeries *areaSeries = new QAreaSeries(series, lowerSeries);
    areaSeries->setName("积分区域");
    areaSeries->setOpacity(0.3);
    chart->addSeries(areaSeries);
}

void MainWindow::showError(const QString& message)
{
    QMessageBox::critical(this, "错误", message);
    ui->statusbar->showMessage(message);
}

void MainWindow::clearResults()
{
    ui->labelResult->clear();
    ui->chartView->chart()->removeAllSeries();
}
